package com.dake.jdk8.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Refkect_06 {

    private static final String FULL_RTE = "com.dake.jdk8.vo.reflect";

    public static void main(String[] args) {
        List<String> stringList = generateList();
//        stringList.forEach(System.out::println);
//        System.out.println(stringList.get(0));
//
//        System.out.println("---------------------");
        String s = stringList.get(0);
        s = s.substring(0, s.indexOf("."));
        if (s.contains("[")) {
            s = s.substring(0, s.indexOf("["));
        }
        s = s.substring(0, 1).toUpperCase() + s.substring(1);

        Object instance = getInstance(FULL_RTE + "." + s);

        String simpleName = instance.getClass().getSimpleName();
        Object[] objects = new Object[1];

        Object data = getData(stringList, instance, objects, new ArrayList<>());
        System.out.println(data);
    }

    private static <T> T getInstance(String className) {
        Class<?> aClass = null;
        try {
            aClass = Class.forName(className);
            return (T) aClass.getDeclaredConstructor().newInstance();
        } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException();
        }
    }

    public static List<String> generateList() {
        return Arrays.asList(
                "Vo.age", "Vo.name", "Vo.a[0].name", "Vo.a[0].age", "Vo.a[1].name", "Vo.a[1].age",
                "Vo.a[0].aef[0].name", "Vo.a[0].aef[0].age",
                "Vo.a[0].aef[0].fgh[0].name", "Vo.a[0].aef[0].fgh[0].age",
                "Vo.a[0].aef[1].fgh[0].name", "Vo.a[0].aef[1].fgh[0].age",
                "Vo.a[0].aef[2].fgh[0].name", "Vo.a[0].aef[2].fgh[0].age",

                "vo.b[0].bef[0].name", "vo.b[0].bef[0].age", "vo.b[0].name","vo.b[0].age");
    }

    private static String field2Upper(String s){
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    private static Object getData(List<String> asList, Object object, Object[] objects, List<Object> objectList) {
        /*
            将查询到的属性路径描述分组，分组规则如下：
            1.如果不包含”[“，则说明该属性路径描述只有两层，第二层为第一层的属性，此时以第一层为分组条件，将第一层下的所有属性都合并在一个分组中；
            2.反之，截取第二个逗号之前的前两个字符串，并以此作为分组条件。
         */
        Map<String, List<String>> collect = asList.stream().collect(Collectors.groupingBy(str -> {
            if (!str.contains("[")) {
                return str.substring(0, str.indexOf("."));
            } else {
                String[] split = str.split("\\.");
                return split[0] + "." + split[1];
//                return str.substring(0, str.indexOf("]") + 1);
            }
        }, Collectors.toList()));


        collect.forEach((k, v) -> {
            System.out.println("k = " + k + ", v = " + v);
            // "abc.bbb[0].aaa", "abc.bbb[0].bbb"
            //abc.bbb[0]
            if (!k.contains("[")){
                v.forEach(a -> {
                    // 截取路径的第二层，即属性
                    String substring = a.substring(a.indexOf(".") + 1);
//                    substring = field2Upper(substring);
                    // 转化为上层对象对象的属性
                    // 给上层对象赋值 给abc对象赋值——即给Object赋值
                    setValue2ObjectByReflection(object, substring, "value");
                });

                // def[1].hij[0]
                //def[1].hij[0].aaa
                // def[1].hij[1].bbb
                // hij[0].aaa
            } else{
                // 本层对象def
                String s1 = k.substring(k.indexOf(".") + 1, k.lastIndexOf("["));
                s1 = field2Upper(s1);
//                s1反射为对象def
                Object instance = getInstance(FULL_RTE + "." + s1);
                // 接收继续递归的属性路径描述集合
                List<String> dscList = new ArrayList<>();


                List<Object> list1 = null;
                if (objectList == null || objectList.isEmpty()) {
                    //                建list<def>对象
                    list1 = new ArrayList<>();
                } else {
                    list1 = objectList;
                }


                v.forEach(finalValue -> {
                    // def[1].aaa
                    // def[1].hij[0].aaa
                    finalValue = finalValue.substring(finalValue.indexOf(".") + 1);
                    String[] split = finalValue.split("\\.");
                    if (split.length == 2) {
//                        将split[1]赋值给本层对象def
                        setValue2ObjectByReflection(instance, split[1], "value");
                    } else {
                        // def[1].hij[0].aaa
                        // def[1].hij[0].bbb
                        // def[1].hij[1].aaa
                        // def[1].hij[1].bbb
                        dscList.add(finalValue);
                    }
                });

                objects[0] = s1.getClass().getSimpleName();

                if (dscList.isEmpty()) {
                    list1.add(instance);
                    // 将list1赋值给objcet对象
                    setValue2ObjectByReflection(object, objects[0] + "List", list1);
                }else {
                    Object data = getData(dscList, s1, objects, list1);
                    list1.add(data);
                    // 将list1赋值给objcet对象
                    setValue2ObjectByReflection(object, objects[0] + "List", list1);
                }
            }
        });
        return object;
    }

    public static void setValue2ObjectByReflection(Object object, String filed, Object value) {
        String methodName = "set" + filed.substring(0, 1).toUpperCase() + filed.substring(1);

        Class<?> type = null;
        try {
            type = object.getClass().getDeclaredField(filed).getType();
            Method method = object.getClass().getDeclaredMethod(methodName, type);
            method.invoke(object, value);
        } catch (NoSuchFieldException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
